package com.webridge.wpmtest.util;


import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;






import wt.access.AccessControlHelper;
import wt.access.AccessPermission;
import wt.admin.AdminDomainRef;
import wt.configurablelink.ConfigurableReferenceLink;
import wt.content.ApplicationData;
import wt.content.ContentHelper;
import wt.content.ContentItem;
import wt.content.ContentRoleType;
import wt.content.ContentServerHelper;
import wt.content.FormatContentHolder;
import wt.doc.WTDocument;
import wt.fc.ObjectReference;
import wt.fc.ObjectToObjectLink;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTObject;
import wt.fc.WTReference;
import wt.folder.Folder;
import wt.inf.container.WTContainer;
import wt.log4j.LogR;
import wt.method.RemoteMethodServer;
import wt.org.WTPrincipal;
import wt.org.WTPrincipalReference;
import wt.org.WTUser;
import wt.part.WTPart;
import wt.pds.StatementSpec;
import wt.pom.Transaction;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionContext;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.type.ClientTypedUtility;
import wt.type.TypeDefinitionForeignKey;
import wt.type.TypeDefinitionReference;
import wt.type.TypedUtility;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.Iterated;
import wt.vc.VersionControlHelper;
import wt.vc.Versioned;
import wt.vc._IterationInfo;
import wt.vc.config.LatestConfigSpec;
import wt.vc.views.View;
import wt.vc.views.ViewHelper;
import wt.vc.wip.CheckoutLink;
import wt.vc.wip.WorkInProgressHelper;

public class WCUtil {
    private final static Logger LOGGER = LogR.getLogger(WCUtil.class.getName());

    public static Persistable getPersistableByOid(String oid) throws WTException {
        Persistable p = null;
        if (!RemoteMethodServer.ServerFlag) {
            try {
                Class aclass[] = { String.class };
                Object aobj[] = { oid };
                p = (Persistable) RemoteMethodServer.getDefault().invoke("getPersistableByOid", WCUtil.class.getName(),
                        null, aclass, aobj);
            } catch (Exception e) {
                // e.printStackTrace();
                LOGGER.error(e.getMessage(), e);
                throw new WTException(e);
            }
        }
        else {
            WTUser previous = null;
            WTPrincipal wtadministrator = null;
            try {
                // session exchange
                previous = (WTUser) SessionHelper.manager.getPrincipal();
                wtadministrator = SessionHelper.manager.getAdministrator();
                SessionContext.setEffectivePrincipal(wtadministrator);
                SessionHelper.manager.setAdministrator();

                ReferenceFactory rf = new ReferenceFactory();
                WTReference wtr = rf.getReference(oid);
                if (wtr != null) {
                    p = wtr.getObject();
                }
            } catch (WTException e) {
                LOGGER.error("getPersistableByOid():", e);
                throw new WTException(e);
            } finally {
                if(previous!=null){
                SessionHelper.manager.setPrincipal(previous.getName());
                SessionContext.setEffectivePrincipal(previous);
                }
            }
        }
        return p;
    }

    public static WTDocument checkOutWTDocument(WTDocument wtdocument1, String description) throws WTException {

        WTDocument wtdocument = wtdocument1;
        if (wtdocument == null) {
            return wtdocument;
        }
        if (!wtdocument.isLatestIteration()) {
            wtdocument = (WTDocument) VersionControlHelper.service.getLatestIteration(wtdocument, false);
        }
        wt.org.WTPrincipal wtprincipal = SessionHelper.manager.getPrincipal();
        AdminDomainRef adminDomainRef = wtdocument.getDomainRef();
        if (SessionServerHelper.manager.isAccessEnforced()
                && !AccessControlHelper.manager.hasAccess(wtprincipal, wtdocument, AccessPermission.MODIFY)) {
            throw new WTException(wtprincipal.getName() + " have no modify permission for doc:"
                    + wtdocument.getNumber() + " in " + wtdocument.getContainer().getName() + "/"
                    + wtdocument.getFolderPath());
        }
        try {
            if (WorkInProgressHelper.isWorkingCopy(wtdocument)) {
                return wtdocument;
            } else if (WorkInProgressHelper.isCheckedOut(wtdocument)) {
                return (WTDocument) WorkInProgressHelper.service.workingCopyOf(wtdocument);
            } else {
                Folder folder = WorkInProgressHelper.service.getCheckoutFolder();
                CheckoutLink checkoutLink = WorkInProgressHelper.service.checkout(wtdocument, folder, description);
                return (WTDocument) checkoutLink.getWorkingCopy();
            }
        } catch (WTPropertyVetoException ex) {
            throw new WTException(ex);
        }
    }

    /**
     * check in wtdocument
     * 
     * @param wtdocument
     * @param description
     * @return
     * @throws WTException
     */
    public static WTDocument checkInWTDocument(WTDocument wtdocument1, String description) throws WTException {
        WTDocument wtdocument = wtdocument1;
        if (wtdocument == null) {
            return wtdocument;
        }

        if (!wtdocument.isLatestIteration())
            wtdocument = (WTDocument) VersionControlHelper.service.getLatestIteration(wtdocument, false);
        try {
            if (WorkInProgressHelper.isWorkingCopy(wtdocument)) {
                return (WTDocument) WorkInProgressHelper.service.checkin(wtdocument, description);
            } else if (WorkInProgressHelper.isCheckedOut(wtdocument)) {
                wtdocument = (WTDocument) WorkInProgressHelper.service.workingCopyOf(wtdocument);
                return (WTDocument) WorkInProgressHelper.service.checkin(wtdocument, description);
            } else return wtdocument;
        } catch (WTPropertyVetoException ex) {
            WTException e = new WTException(ex);
            throw e;
        }
    }

    public static ApplicationData setPrimaryContent(WTDocument document, String fileName,
            InputStream content) throws WTException {
        if (!RemoteMethodServer.ServerFlag) {
            try {
                return (ApplicationData) RemoteMethodServer.getDefault().invoke("setPrimaryContent",
                        WCUtil.class.getName(), null,
                        new Class[] { WTDocument.class, String.class, InputStream.class },
                        new Object[] { document, fileName, content });
            } catch (RemoteException e) {
                Throwable cause = e.getCause();
                if (cause instanceof WTException) {
                    throw (WTException) cause;
                }
                throw new WTException(cause);
            } catch (InvocationTargetException e) {
                throw new WTException(e);
            }
        }
        Transaction tx = null;
        try {
            tx = new Transaction();
            tx.start();
            ApplicationData applicationdata = ApplicationData.newApplicationData(document);
            applicationdata.setFileName(fileName);
            applicationdata.setRole(ContentRoleType.PRIMARY);
            document = (WTDocument) ContentHelper.service.getContents(document);
            ContentItem item = document.getPrimary();
            if (item != null) {
                ContentServerHelper.service.deleteContent(document, item);
            }
            ContentServerHelper.service.updateContent(document, applicationdata, content);
            ContentServerHelper.service.updateHolderFormat((FormatContentHolder) document);
            tx.commit();
            tx = null;
            return applicationdata;
        } catch (Exception e) {
            if (e instanceof WTException) {
                throw (WTException) e;
            }
            throw new WTException(e);
        } finally {
            if (tx != null) {
                tx.rollback();
            }
        }
    }
    public static List<WTPart> getPartByName(String partName, String state,
            String type) throws WTException {
        List<WTPart> partList = new ArrayList<WTPart>();
        View view = ViewHelper.service.getView("Design");
        QuerySpec qs = new QuerySpec(WTPart.class);
        SearchCondition sc = new SearchCondition(WTPart.class, WTPart.NAME,
                SearchCondition.EQUAL, partName, false);
        qs.appendWhere(sc, new int[] { 0 });
        if (view != null) {
            qs.appendAnd();
            sc = new SearchCondition(WTPart.class, "view.key.id",
                    SearchCondition.EQUAL, view.getPersistInfo()
                            .getObjectIdentifier().getId());
            qs.appendWhere(sc, new int[] { 0 });
        }
        LOGGER.debug("StatementSpec=" + qs);
        QueryResult qr = PersistenceServerHelper.manager
                .query((StatementSpec) qs);
        qr = new LatestConfigSpec().process(qr);
        WTPart part = null;
        while (qr.hasMoreElements()) {
            part = (WTPart) qr.nextElement();
            String ibaType = TypedUtility.getTypeIdentifier(part).getTypename();
            String partState = part.getState().toString();
            LOGGER.debug("ibaType=" + ibaType + ",partState = " + partState);
            if (partState.indexOf(state) != -1 && ibaType.indexOf(type) != -1) {
                partList.add(part);
            }
        }
        return partList;
    }
    public static QueryResult queryConfigurableLink(Persistable roleAObject, Persistable roleBObject, Class linkClass)
    {
        try
        {
        QueryResult qr = new QueryResult();
        if (roleAObject == null && roleBObject == null) {
            return qr;
        }
        QuerySpec qs = new QuerySpec(linkClass);
        if (roleAObject != null) {
            qs.appendWhere(new SearchCondition(linkClass,
                    ObjectToObjectLink.ROLE_AOBJECT_REF + "." + ObjectReference.KEY, SearchCondition.EQUAL,
                    PersistenceHelper.getObjectIdentifier(roleAObject)),
                    new int[] { 0 });
        }
        if (roleBObject != null) {
            if (qs.getConditionCount() > 0) {
                qs.appendAnd();
            }
            qs.appendWhere(new SearchCondition(linkClass,
                    ObjectToObjectLink.ROLE_BOBJECT_REF + "." + ObjectReference.KEY, SearchCondition.EQUAL,
                    PersistenceHelper.getObjectIdentifier(roleBObject)),
                    new int[] { 0 });
        }
        qr = PersistenceHelper.manager.find((StatementSpec) qs);
        return qr;
        }
        catch (WTException e) {
            // TODO Auto-generated catch block
            LOGGER.debug("queryConfigurableLink() occur exception :", e);
        }
        return null;
    }
    public static String getVersionInfo(WTObject wto) {
        String versionInfo = "";
        if (wto instanceof Versioned) {
            Versioned ved = (Versioned) wto;
            String version = ved.getVersionIdentifier().getValue();
            String iteration = ved.getIterationIdentifier().getValue();
            if (version != null && iteration != null) {
                versionInfo = version + "." + iteration;
            }
        }
        else {
            LOGGER.debug("the wto is not versioned, return null ");
        }
        return versionInfo;
    }
    public static void setCreatorOrModifier(Iterated obj, WTPrincipalReference uref, String methodName) {
        try {
            Class[] pp = new Class[] { WTPrincipalReference.class };
            Method setCreatorOrModifier = _IterationInfo.class.getDeclaredMethod(methodName, pp);// setCreator;setModifier
            setCreatorOrModifier.setAccessible(true);
            obj = (Iterated) PersistenceHelper.manager.refresh((Persistable) obj, false, true);
            setCreatorOrModifier.invoke(obj.getIterationInfo(), new Object[] { uref });
            PersistenceServerHelper.manager.update(obj);

        } catch (Exception e) {
            
            LOGGER.error(LOGGER, e);
        }
    }
    
    public static WTContainer getWtContainerByName(String name) throws WTException
    {
        WTContainer obj = null;
        if (!RemoteMethodServer.ServerFlag)
        {
            try
            {
                Class aclass[] = 
                { String.class };
                Object aobj[] =
                { name };
                obj = (WTContainer) RemoteMethodServer.getDefault().invoke("getWtContainerByName",
                        WCUtil.class.getName(), null, aclass, aobj);
            } catch (Exception e)
            {
                LOGGER.error(e.getMessage(), e);
                throw new WTException(e);
            }
        }
        else
        {
            QuerySpec qs = new QuerySpec(WTContainer.class);
            QueryResult qr = null;
            SearchCondition sc = new SearchCondition(WTContainer.class, WTContainer.NAME, "=", name);
            qs.appendWhere(sc);
            qr = PersistenceServerHelper.manager.query(qs);

            while (qr.hasMoreElements())
            {
                obj = (WTContainer) qr.nextElement();
            }
        }
        return obj;
    }
}
